以下筆記摘錄自『 The Go Workshop 』。
Go語言採用了一個簡單的記憶體管理系統叫堆疊(stack),每個參數都會在堆疊中獲得自己的記憶體,缺點是有越多值在函式之間傳遞,這樣重複的動作就會消耗越多的記憶體。
但其實還有一種在函式傳值得替代方式,使用的記憶體較少,這種方式不會複製值,而是建立稱指標(pointer)的東西傳遞給函式。
建立一個指標後,Go語言會將值放在所謂的堆積(heap)記憶體空間,堆積允許一個值存在,直到沒有任何指標參照到他為止。Go語言會用所謂的垃圾回收機制(garbage collection)程序來回收這些記憶體。這種機制會在背景定期運作,無需特別操心。
Remark:
有時就算值沒有設置任何指標,也會因為其他原因被放進堆積裡面,值究竟該放到堆疊還是堆積上,我們無法介入,因為記憶體管理並非Go規格的一部分,而是被視為內部實作細節,所以上述所說的特性只是一般性指引,非鐵則。
指標會有未設定(is not set)的狀態,他沒有儲存目標值的地址時會回傳nil,而nil這個特殊值在Go語言中代表無值。
var <變數> *<型別>
<變數> := new(<型別>)
var <變數> = new(<型別>)
<變數 1> := &<變數 2>
若要真正取得指標的關聯值(及指標指向的記憶體所儲存的內容),必須把 * 算符放在變數前面解除(derederence)指標參照,真正取值。
<值> = *<指標變數>
常見錯誤是嘗試去解除一個無值指標(亦即nil),Go編輯器無法事先警告這點,所以最好養成習慣在解除指標的參照前,先檢查它是否是nil。
For example,
package main
import (
"fmt"
)
func main() {
var count1 *int
count2 := new(int)
countTemp := 5
count3 := &countTemp
if count1 != nil {
fmt.Printf("count1: %#v\n", *count1)
}
if count2 != nil {
fmt.Printf("count2: %#v\n", *count2)
}
if count3 != nil {
fmt.Printf("count3: %#v\n", *count3)
}
}
//輸出
count2: 0
count3: 5